package com.sunda.spmsoversea.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sunda.spmscommon.ResponseResult;
import com.sunda.spmscommon.feign.IFeignServiceCommon;
import com.sunda.spmsoversea.dto.OverseaWhsMoveSearchDTO;
import com.sunda.spmsoversea.dto.OverseaWhsMoveUpdateDTO;
import com.sunda.spmsoversea.entity.OverseaWhsMove;
import com.sunda.spmsoversea.entity.OverseaWhsMoveDtl;
import com.sunda.spmsoversea.entity.WhsStorageInventory;
import com.sunda.spmsoversea.mapper.OverseaWhsMoveMapper;
import com.sunda.spmsoversea.service.*;
import feign.FeignException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.List;
import java.util.Map;
import java.util.UUID;

import static com.sunda.spmsoversea.constant.CommonConstant.SUCCESS;
import static com.sunda.spmsoversea.constant.CommonConstant.sapLog;
import static com.sunda.spmsoversea.constant.SapConstant.SAP_SUCCESS;
import static com.sunda.spmsoversea.constant.WhsStorageInventoryConstant.*;
import static com.sunda.spmsoversea.enums.OverseaWhsMoveEnum.*;

/**
 * <p>
 * 海外仓调拨业务 服务实现类
 * </p>
 *
 * @author Wayne
 * @since 2022-01-20
 */
@Slf4j
@Service
public class OverseaWhsMoveServiceImpl extends ServiceImpl<OverseaWhsMoveMapper, OverseaWhsMove> implements IOverseaWhsMoveService {

    @Autowired
    IFeignServiceCommon iFeignServiceCommon;

    @Autowired
    IFormatDataToSapService iFormatDataToSapService;

    @Autowired
    IWhsStorageInventoryService iWhsStorageInventoryService;

    @Autowired
    IWhsOperateLogService iWhsOperateLogService;

    @Autowired
    IOverseaOperateLogService iOverseaOperateLogService;

    @Autowired
    IOverseaWhsMoveDtlService iOverseaWhsMoveDtlService;

    /** 获取海外仓调拨任务表头分页列表 */
    @Override
    public IPage getOverseaWhsMovePage(OverseaWhsMoveSearchDTO overseaWhsMoveSearchDTO) {
        IPage iPage = overseaWhsMoveSearchDTO.getPage();
        List<Map<String, Object>> mapList = this.baseMapper.getOverseaWhsMovePage(iPage, overseaWhsMoveSearchDTO);
        iPage.setRecords(mapList);
        return iPage;
    }

    /** 获取海外仓调拨任务一条明细 */
    @Override
    public Map<String, Object> getOverseaWhsMoveByUuid(String uuid) {
        if (StringUtils.isEmpty(uuid)){
            return null;
        }
        return this.baseMapper.getOverseaWhsMoveByUuid(uuid);
    }

    /** 获取海外仓调拨任务详细明细信息 */
    @Override
    public List<Map<String, Object>> getOverseaWhsMoveDtlList(String uuid) {
        if (StringUtils.isEmpty(uuid)){
            return null;
        }
        return iOverseaWhsMoveDtlService.getOverseaWhsMoveDtlList(uuid);
    }

    /** 更新或新建海外仓调拨任务及明细，目标状态：1新建或更新；2提交SPMS更新两边仓库库存； */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized ResponseResult updateOverseaWhsMove(OverseaWhsMoveUpdateDTO overseaWhsMoveUpdateDTO, String userId) {
        try {
            ResponseResult checkUpdate = checkUpdateParam(overseaWhsMoveUpdateDTO);
            if (checkUpdate.getCode() != SUCCESS){
                return checkUpdate;
            }
            String uuid = "";
            String spmsStatus = overseaWhsMoveUpdateDTO.getSpmsStatus();
            if (StringUtils.isEmpty(overseaWhsMoveUpdateDTO.getUuid())){
                // 新建
                uuid = UUID.randomUUID().toString().replaceAll("-", "").toLowerCase();
                int createHead = createOverseaWhsMove(overseaWhsMoveUpdateDTO, uuid, userId);
                if (createHead < 1){
                    log.info("=======updateOverseaWhsMove RuntimeException=========\n");
                    throw new RuntimeException("创建海外仓调拨任务错误");
                }
                int createItem = createOverseaWhsMoveDtl(overseaWhsMoveUpdateDTO, uuid);
                if (createItem < 1){
                    log.info("=======updateOverseaWhsMove RuntimeException=========\n");
                    throw new RuntimeException("创建海外仓调拨任务明细错误");
                }
                iOverseaOperateLogService.addOverseaOperateLog(userId, uuid, OVERSEA_WHS_MOVE_CREATE.getDescZh(), OVERSEA_WHS_MOVE_CREATE.getDescEn(), "");
            } else {
                // 更新
                uuid = overseaWhsMoveUpdateDTO.getUuid();
                int updateHead = updateOverseaWhsMoveHead(overseaWhsMoveUpdateDTO, uuid);
                if (updateHead < 1){
                    log.info("=======updateOverseaWhsMove RuntimeException=========\n");
                    throw new RuntimeException("更新海外仓调拨任务错误");
                }
                QueryWrapper<OverseaWhsMoveDtl> queryWrapperDtl = new QueryWrapper<OverseaWhsMoveDtl>().eq("UUID", uuid);
                iOverseaWhsMoveDtlService.remove(queryWrapperDtl);
                int createItem = createOverseaWhsMoveDtl(overseaWhsMoveUpdateDTO, uuid);
                if (createItem < 1){
                    log.info("=======updateOverseaWhsMove RuntimeException=========\n");
                    throw new RuntimeException("创建海外仓调拨任务明细错误");
                }
                if (OVERSEA_WHS_MOVE_UPDATE.getCode().equals(spmsStatus)){
                    iOverseaOperateLogService.addOverseaOperateLog(userId, uuid, OVERSEA_WHS_MOVE_UPDATE.getDescZh(), OVERSEA_WHS_MOVE_UPDATE.getDescEn(), "");
                }
                if (OVERSEA_WHS_MOVE_SUBMIT.getCode().equals(spmsStatus)){
                    iOverseaOperateLogService.addOverseaOperateLog(userId, uuid, OVERSEA_WHS_MOVE_SUBMIT.getDescZh(), OVERSEA_WHS_MOVE_SUBMIT.getDescEn(), "");
                }
            }
            if (OVERSEA_WHS_MOVE_SUBMIT.getCode().equals(spmsStatus)){
                // 更新库存，isCancel: 是否为冲销业务的库存更新操作，正常提交业务传值 false；冲销操作库存更新传值 true；
                ResponseResult updateStorageInventory = updateWhsStorageInventory(uuid, userId, false);
                if (updateStorageInventory.getCode() != SUCCESS){
                    log.info("=======RuntimeException=========\n" + updateStorageInventory.getMsg());
                    throw new RuntimeException("储位库存更新错误\n" + updateStorageInventory.getMsg());
                }
            }
            return ResponseResult.success().add("overseaWhsMove", getOverseaWhsMoveByUuid(uuid))
                    .add("overseaWhsMoveDtl", getOverseaWhsMoveDtlList(uuid));
        } catch (Exception e){
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ResponseResult.error().add("error", e.getMessage());
        }
    }

    /** isCancel: 是否为冲销业务的库存更新操作，正常提交业务传值 false；冲销操作库存更新传值 true； */
    synchronized ResponseResult updateWhsStorageInventory(String uuid, String userId, boolean isCancel){
        OverseaWhsMove overseaWhsMove = this.baseMapper.selectOne(new QueryWrapper<OverseaWhsMove>().eq("UUID", uuid));
        List<OverseaWhsMoveDtl> dtlList = iOverseaWhsMoveDtlService.list(new QueryWrapper<OverseaWhsMoveDtl>().eq("UUID", uuid));
        String werksOut = overseaWhsMove.getWerksMoveOut();
        String whsLocationCodeOut = overseaWhsMove.getWhsLocationCodeMoveOut();
        String werksIn = overseaWhsMove.getWerksMoveIn();
        String whsLocationCodeIn = overseaWhsMove.getWhsLocationCodeMoveIn();
        String movementType = overseaWhsMove.getMovementType();
        for (OverseaWhsMoveDtl dtl : dtlList){
            String materialNo = dtl.getMaterialNo();
            double actualQtyBasicUnit = dtl.getActualQtyMoveOut();
            if (actualQtyBasicUnit > 0){
                // 正向业务的出库储位扣减库存，冲销业务为增加库存储位
                JSONArray storageInfoArray = JSONArray.parseArray(dtl.getActualStorageInfoMoveOut());
                for (int i = 0; i < storageInfoArray.size(); i ++){
                    JSONObject storageInfoObj = storageInfoArray.getJSONObject(i);
                    String storageUuid = storageInfoObj.getString("storageUuid");
                    double qty = storageInfoObj.getDoubleValue("qty");
                    if (qty > 0){
                        if (!isCancel){
                            ResponseResult updateInventory = iWhsStorageInventoryService.updateWhsStorageInventory(storageUuid, materialNo, qty, SUB);
                            if (updateInventory.getCode() != SUCCESS){
                                return updateInventory;
                            }
                            /** 海外仓调拨出库 **/
                            String comments = "海外仓调拨出库";
                            iWhsOperateLogService.insertWhsOperateLog(storageUuid, materialNo, qty, OPERATION_TYPE3, uuid, comments, userId, "海外仓调拨", werksOut, whsLocationCodeOut, movementType);
                        } else {
                            ResponseResult updateInventory = iWhsStorageInventoryService.updateWhsStorageInventory(storageUuid, materialNo, qty, ADD);
                            if (updateInventory.getCode() != SUCCESS){
                                return updateInventory;
                            }
                            /** 海外仓调拨出库撤销 **/
                            String comments = "海外仓调拨出库撤销";
                            iWhsOperateLogService.insertWhsOperateLog(storageUuid, materialNo, qty, OPERATION_TYPE2, uuid, comments, userId, "海外仓调拨撤销", werksOut, whsLocationCodeOut, movementType);
                        }
                    }
                }
                // 正向业务的入库储位增加库存，冲销业务为扣减库存储位
                JSONArray storageInfoArrayIn = JSONArray.parseArray(dtl.getActualStorageInfoMoveIn());
                for (int i = 0; i < storageInfoArrayIn.size(); i ++){
                    JSONObject storageInfoObj = storageInfoArrayIn.getJSONObject(i);
                    String storageUuid = storageInfoObj.getString("storageUuid");
                    double qty = storageInfoObj.getDoubleValue("qty");
                    if (qty > 0){
                        if (!isCancel){
                            ResponseResult updateInventory = iWhsStorageInventoryService.updateWhsStorageInventory(storageUuid, materialNo, qty, ADD);
                            if (updateInventory.getCode() != SUCCESS){
                                return updateInventory;
                            }
                            /** 海外仓调拨入库 **/
                            String comments = "海外仓调拨入库";
                            iWhsOperateLogService.insertWhsOperateLog(storageUuid, materialNo, qty, OPERATION_TYPE2, uuid, comments, userId, "海外仓调拨", werksIn, whsLocationCodeIn, movementType);
                        } else {
                            ResponseResult updateInventory = iWhsStorageInventoryService.updateWhsStorageInventory(storageUuid, materialNo, qty, SUB);
                            if (updateInventory.getCode() != SUCCESS){
                                return updateInventory;
                            }
                            /** 海外仓调拨入库撤销 **/
                            String comments = "海外仓调拨入库撤销";
                            iWhsOperateLogService.insertWhsOperateLog(storageUuid, materialNo, qty, OPERATION_TYPE3, uuid, comments, userId, "海外仓调拨撤销", werksIn, whsLocationCodeIn, movementType);
                        }
                    }
                }
            }
        }
        return ResponseResult.success();
    }

    ResponseResult checkUpdateParam(OverseaWhsMoveUpdateDTO overseaWhsMoveUpdateDTO){
        if (overseaWhsMoveUpdateDTO == null){
            return ResponseResult.error("请求参数不能为空");
        }
        String spmsStatus = overseaWhsMoveUpdateDTO.getSpmsStatus();
        if (StringUtils.isEmpty(spmsStatus)){
            return ResponseResult.error("请求参数目标状态不能为空");
        }
        String uuid = overseaWhsMoveUpdateDTO.getUuid();
        if (StringUtils.isEmpty(uuid)){
            //新建
            if (StringUtils.isEmpty(overseaWhsMoveUpdateDTO.getCreateDate())){
                return ResponseResult.error("新建订单创建日期不允许为空");
            }
            if (StringUtils.isEmpty(overseaWhsMoveUpdateDTO.getWerksMoveOut()) || StringUtils.isEmpty(overseaWhsMoveUpdateDTO.getWerksMoveIn())){
                return ResponseResult.error("新建订单调入调出工厂不允许为空");
            }
            if (StringUtils.isEmpty(overseaWhsMoveUpdateDTO.getWhsLocationCodeMoveOut()) ||
                    StringUtils.isEmpty(overseaWhsMoveUpdateDTO.getWhsLocationCodeMoveIn())){
                return ResponseResult.error("新建订单调入调出仓库不允许为空");
            }
        } else {
            //更新
            Integer dataVersion = overseaWhsMoveUpdateDTO.getDataVersion();
            OverseaWhsMove overseaWhsMove = this.baseMapper.selectOne(new QueryWrapper<OverseaWhsMove>().eq("UUID", uuid));
            if (overseaWhsMove == null){
                return ResponseResult.error("更新调拨任务不存在");
            }
            if (!dataVersion.equals(overseaWhsMove.getDataVersion())){
                return ResponseResult.error("请求调拨任务已更新，请刷新重试");
            }
        }
        if (OVERSEA_WHS_MOVE_SUBMIT.getCode().equals(spmsStatus)){
            //直接扣库存，检查库存是否够扣减
            ResponseResult checkInv = checkInventory(overseaWhsMoveUpdateDTO);
            if (checkInv.getCode() != SUCCESS){
                return checkInv;
            }
        }
        return ResponseResult.success();
    }

    ResponseResult checkInventory(OverseaWhsMoveUpdateDTO overseaWhsMoveUpdateDTO){
        List<OverseaWhsMoveDtl> overseaWhsMoveDtlList = overseaWhsMoveUpdateDTO.getOverseaWhsMoveDtlList();
        if (overseaWhsMoveDtlList == null || overseaWhsMoveDtlList.size() == 0){
            return ResponseResult.error("调拨明细信息不能为空");
        }
        for (int k = 0; k < overseaWhsMoveDtlList.size(); k ++){
            OverseaWhsMoveDtl overseaWhsMoveDtl = overseaWhsMoveDtlList.get(k);
            String item = overseaWhsMoveDtl.getItemNo();
            String materialNo = overseaWhsMoveDtl.getMaterialNo();
            String storageInfo = overseaWhsMoveDtl.getActualStorageInfoMoveOut();
            double actualQtyBasicUnit = overseaWhsMoveDtl.getActualQtyMoveOut();
            if (actualQtyBasicUnit > 0){
                if (StringUtils.isEmpty(storageInfo)){
                    return ResponseResult.error("实出数量大于0的行:" + item + "，料号:" + materialNo + "储位信息无效");
                }
                //storageInfoArray 结构参考：[{"storageUuid":"cbd9576a4e53461fe0530101007f3e24","qty":5,"storageNo":"A010101","unitValue":5}]
                JSONArray storageInfoArray = JSONArray.parseArray(storageInfo);
                for (int i = 0; i < storageInfoArray.size(); i ++){
                    JSONObject storageInfoObj = storageInfoArray.getJSONObject(i);
                    String storageUuid = storageInfoObj.getString("storageUuid");
                    double qty = storageInfoObj.getDoubleValue("qty");
                    String storageNo = storageInfoObj.getString("storageNo");
                    if (qty > 0){
                        WhsStorageInventory whsStorageInventory = iWhsStorageInventoryService.getWhsStorageInventory(storageUuid, materialNo);
                        if (whsStorageInventory == null){
                            return ResponseResult.error("物料号" + materialNo + "在储位" + storageNo + "无可用库存");
                        }
                        if (qty > whsStorageInventory.getAvailableQty()){
                            return ResponseResult.error("物料号" + materialNo + "在储位" + storageNo + "可用库存不足");
                        }
                    }
                }
            }
        }
        return ResponseResult.success();
    }

    int createOverseaWhsMove(OverseaWhsMoveUpdateDTO dto, String uuid, String userId){
        OverseaWhsMove overseaWhsMove = new OverseaWhsMove();
        overseaWhsMove.setUuid(uuid);
        overseaWhsMove.setSubject(dto.getSubject());
        overseaWhsMove.setCreateDate(dto.getCreateDate());
        overseaWhsMove.setSpmsStatus(StringUtils.isEmpty(dto.getSpmsStatus()) ? "1" : dto.getSpmsStatus());
        overseaWhsMove.setMovementType(dto.getMovementType());
        overseaWhsMove.setWerksMoveOut(dto.getWerksMoveOut());
        overseaWhsMove.setWhsLocationCodeMoveOut(dto.getWhsLocationCodeMoveOut());
        overseaWhsMove.setRemarkMoveOut(dto.getRemarkMoveOut());
        overseaWhsMove.setWerksMoveIn(dto.getWerksMoveIn());
        overseaWhsMove.setWhsLocationCodeMoveIn(dto.getWhsLocationCodeMoveIn());
        overseaWhsMove.setRemarkMoveIn(dto.getRemarkMoveIn());
        overseaWhsMove.setRelateDocument(dto.getRelateDocument());
        overseaWhsMove.setCreateUserid(userId);
        return this.baseMapper.insert(overseaWhsMove);
    }

    int createOverseaWhsMoveDtl(OverseaWhsMoveUpdateDTO overseaWhsMoveUpdateDTO, String uuid){
        List<OverseaWhsMoveDtl> overseaWhsMoveDtlList = overseaWhsMoveUpdateDTO.getOverseaWhsMoveDtlList();
        int result = 0;
        for (int i = 0; i < overseaWhsMoveDtlList.size(); i ++){
            OverseaWhsMoveDtl overseaWhsMoveDtl = overseaWhsMoveDtlList.get(i);
            OverseaWhsMoveDtl dtl = new OverseaWhsMoveDtl();
            dtl.setUuid(uuid);
            dtl.setItemNo(String.valueOf((i + 1) * 10));
            dtl.setMaterialNo(overseaWhsMoveDtl.getMaterialNo());
            dtl.setQtyMoveOut(overseaWhsMoveDtl.getQtyMoveOut());
            dtl.setStorageInfoMoveOut(overseaWhsMoveDtl.getStorageInfoMoveOut());
            dtl.setActualQtyMoveOut(overseaWhsMoveDtl.getActualQtyMoveOut());
            dtl.setActualStorageInfoMoveOut(overseaWhsMoveDtl.getActualStorageInfoMoveOut());
            dtl.setRemarkMoveOut(overseaWhsMoveDtl.getRemarkMoveOut());
            dtl.setActualQtyMoveIn(overseaWhsMoveDtl.getActualQtyMoveIn());
            dtl.setActualStorageInfoMoveIn(overseaWhsMoveDtl.getActualStorageInfoMoveIn());
            dtl.setRemarkMoveIn(overseaWhsMoveDtl.getRemarkMoveIn());
            dtl.setSupplierNo(overseaWhsMoveDtl.getSupplierNo());
            if (iOverseaWhsMoveDtlService.save(dtl)){
                result += 1;
            }
        }
        return result;
    }

    int updateOverseaWhsMoveHead(OverseaWhsMoveUpdateDTO dto, String uuid){
        QueryWrapper<OverseaWhsMove> queryWrapper = new QueryWrapper<OverseaWhsMove>().eq("UUID", uuid);
        OverseaWhsMove overseaWhsMove = this.baseMapper.selectOne(queryWrapper);
        overseaWhsMove.setSubject(dto.getSubject());
        overseaWhsMove.setSpmsStatus(dto.getSpmsStatus());
        overseaWhsMove.setRemarkMoveOut(dto.getRemarkMoveOut());
        overseaWhsMove.setRemarkMoveIn(dto.getRemarkMoveIn());
        overseaWhsMove.setRelateDocument(dto.getRelateDocument());
        return this.baseMapper.update(overseaWhsMove, queryWrapper);
    }

    /** 海外仓调拨任务提交SAP：2——3、2——4 或 3——4 */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized ResponseResult submitOverseaWhsMoveSap(String uuid, String postingDate, Integer dataVersion, String userId) {
        try {
            ResponseResult checkSubmit = checkSubmitSap(uuid, postingDate, dataVersion);
            if (checkSubmit.getCode() != SUCCESS){
                return checkSubmit;
            }
            QueryWrapper<OverseaWhsMove> queryWrapper = new QueryWrapper<OverseaWhsMove>().eq("UUID", uuid);
            Map<String, Object> submitSapHead = this.baseMapper.submitSapHead(uuid, postingDate);
            List<Map<String, Object>> submitSapItem = this.baseMapper.submitSapItem(uuid);
            if (submitSapHead == null || submitSapItem == null || submitSapItem.size() == 0){
                return ResponseResult.error("查询无可提交SAP项目");
            }
            JSONObject dataToSap = iFormatDataToSapService.formatDataToSap(submitSapHead, submitSapItem, "Z_SPMS_ANOMALY_POST", "ANOMALY_POST");
            log.info("=======海外仓调拨任务请求SAP dataToSap=========\n" + dataToSap);
            JSONObject message = JSONObject.parseObject(iFeignServiceCommon.sendRestToSapCommon(dataToSap));
            log.info("=======海外仓调拨任务请求SAP响应结果 message=========\n" + message);
            JSONObject RETURN_DATA_Undercharged = message.getJSONObject("RESPONSE").getJSONObject("RETURN_DATA");
            OverseaWhsMove overseaWhsMove = new OverseaWhsMove();
            if (SAP_SUCCESS.equals(RETURN_DATA_Undercharged.getString("O_TYPE"))) {
                String sapVoucherNumber = RETURN_DATA_Undercharged.getString("O_MBLNR").trim();
                String sapVoucherYear = RETURN_DATA_Undercharged.getString("O_MJAHR").trim();
                overseaWhsMove.setPostingDate(postingDate);
                overseaWhsMove.setSapVoucherNumber(sapVoucherNumber);
                overseaWhsMove.setSapVoucherYear(sapVoucherYear);
                overseaWhsMove.setSpmsStatus(OVERSEA_WHS_MOVE_SUBMIT_SAP.getCode());
                this.baseMapper.update(overseaWhsMove, queryWrapper);

                iOverseaOperateLogService.addOverseaOperateLog(userId, uuid, OVERSEA_WHS_MOVE_SUBMIT_SAP.getDescZh() + ":" + sapVoucherNumber,
                        OVERSEA_WHS_MOVE_SUBMIT_SAP.getDescEn(), sapLog, dataToSap.toJSONString(), message.toJSONString(), "海外仓调拨提交SAP成功");
                return ResponseResult.success("海外仓调拨任务提交SAP成功")
                        .add("overseaWhsMove", getOverseaWhsMoveByUuid(uuid));
            } else {
                overseaWhsMove.setPostingDate(postingDate);
                overseaWhsMove.setSpmsStatus(OVERSEA_WHS_MOVE_SUBMIT_SAP_ERROR.getCode());
                this.baseMapper.update(overseaWhsMove, queryWrapper);
                iOverseaOperateLogService.addOverseaOperateLog(userId, uuid, OVERSEA_WHS_MOVE_SUBMIT_SAP_ERROR.getDescZh(),
                        OVERSEA_WHS_MOVE_SUBMIT_SAP_ERROR.getDescEn(), sapLog, dataToSap.toJSONString(), message.toJSONString(), "海外仓调拨提交SAP失败");
                return ResponseResult.error("海外仓调拨任务提交SAP失败")
                        .add("sapReturnedMessage", message)
                        .add("dataToSap", dataToSap)
                        .add("overseaWhsMove", getOverseaWhsMoveByUuid(uuid));
            }
        } catch (FeignException feignException){
            feignException.printStackTrace();
            return ResponseResult.error("请求SAP失败 FeignException").add("error", feignException.getMessage());
        }catch (Exception e){
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ResponseResult.error("海外仓调拨任务更新单据或提交SAP失败 Exception").add("error", e.getMessage());
        }
    }

    ResponseResult checkSubmitSap(String uuid, String postingDate, Integer dataVersion){
        if (StringUtils.isEmpty(uuid)){
            return ResponseResult.error("请求参数错误");
        }
        if (StringUtils.isEmpty(postingDate) || dataVersion == null){
            return ResponseResult.error("请求参数错误");
        }
        OverseaWhsMove overseaWhsMove = this.baseMapper.selectOne(new QueryWrapper<OverseaWhsMove>().eq("UUID", uuid));
        if (overseaWhsMove == null){
            return ResponseResult.error("更新调拨任务不存在");
        }
        if (!dataVersion.equals(overseaWhsMove.getDataVersion())){
            return ResponseResult.error("请求调拨任务已更新，请刷新重试");
        }
        String spmsStatus = overseaWhsMove.getSpmsStatus();
        if (!OVERSEA_WHS_MOVE_SUBMIT.getCode().equals(spmsStatus) &&
                !OVERSEA_WHS_MOVE_SUBMIT_SAP_ERROR.getCode().equals(spmsStatus)){
            return ResponseResult.error("请求调拨任务当前状态禁止此操作");
        }
        return ResponseResult.success();
    }

    /** 海外仓调拨任务关闭 1-0；*/
    @Override
    public synchronized ResponseResult closeOverseaWhsMoveTask(String uuid, Integer dataVersion, String userId) {
        if (StringUtils.isEmpty(uuid) || dataVersion == null){
            return ResponseResult.error("请求参数错误");
        }
        QueryWrapper<OverseaWhsMove> queryWrapper = new QueryWrapper<OverseaWhsMove>().eq("UUID", uuid);
        OverseaWhsMove overseaWhsMove = this.baseMapper.selectOne(queryWrapper);
        if (overseaWhsMove == null){
            return ResponseResult.error("更新调拨任务不存在");
        }
        if (!dataVersion.equals(overseaWhsMove.getDataVersion())){
            return ResponseResult.error("请求调拨任务已更新，请刷新重试");
        }
        String spmsStatus = overseaWhsMove.getSpmsStatus();
        if (!OVERSEA_WHS_MOVE_CREATE.getCode().equals(spmsStatus)){
            return ResponseResult.error("请求调拨任务当前状态禁止此操作");
        }
        overseaWhsMove.setSpmsStatus(OVERSEA_WHS_MOVE_CLOSE.getCode());
        this.baseMapper.update(overseaWhsMove, queryWrapper);
        iOverseaOperateLogService.addOverseaOperateLog(userId, uuid, OVERSEA_WHS_MOVE_CLOSE.getDescZh(), OVERSEA_WHS_MOVE_CLOSE.getDescEn(), "");
        return ResponseResult.success().add("overseaWhsMove", getOverseaWhsMoveByUuid(uuid));
    }

    /** 调拨任务撤销，状态变化：2——1，3——1，4——1，都要更新库存 */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized ResponseResult cancelOverseaWhsMove(String uuid, Integer dataVersion, String cancelPostingDate, String userId) {
        try {
            ResponseResult checkCancel = checkCancel(uuid, dataVersion, cancelPostingDate);
            if (checkCancel.getCode() != SUCCESS){
                return checkCancel;
            }
            QueryWrapper queryWrapper = new QueryWrapper<OverseaWhsMove>().eq("UUID", uuid);
            OverseaWhsMove overseaWhsMove = this.baseMapper.selectOne(queryWrapper);
            String spmsStatus = overseaWhsMove.getSpmsStatus();
            if (OVERSEA_WHS_MOVE_SUBMIT.getCode().equals(spmsStatus) || OVERSEA_WHS_MOVE_SUBMIT_SAP_ERROR.getCode().equals(spmsStatus)){
                ResponseResult updateInv = updateWhsStorageInventory(uuid, userId, true);
                if (updateInv.getCode() != SUCCESS){
                    log.info("=======RuntimeException=========\n" + updateInv.getMsg());
                    throw new RuntimeException("储位库存更新错误\n" + updateInv.getMsg());
                }
                overseaWhsMove.setSpmsStatus(OVERSEA_WHS_MOVE_UPDATE.getCode());
                this.baseMapper.update(overseaWhsMove, queryWrapper);
                iOverseaOperateLogService.addOverseaOperateLog(userId, uuid, OVERSEA_WHS_MOVE_CANCEL.getDescZh(), OVERSEA_WHS_MOVE_CANCEL.getDescEn(), "");
                return ResponseResult.success().add("overseaWhsMove", getOverseaWhsMoveByUuid(uuid))
                        .add("overseaWhsMoveDtl", getOverseaWhsMoveDtlList(uuid));
            } else if (OVERSEA_WHS_MOVE_SUBMIT_SAP.getCode().equals(spmsStatus)){
                Map<String, Object> dataHeadAnomaly = this.baseMapper.dataHeadCancelAnomaly(uuid, cancelPostingDate);
                JSONObject dataToSapCancelAnomaly = iFormatDataToSapService.formatDataToSap(dataHeadAnomaly, null, "Z_SPMS_CANCEL", "SPMS_CANCEL");
                log.info("=======海外调拨凭证撤销请求SAP dataToSap=========\n" + dataToSapCancelAnomaly);
                JSONObject messageCancelAnomaly = JSONObject.parseObject(iFeignServiceCommon.sendRestToSapCommon(dataToSapCancelAnomaly));
                log.info("=======海外调拨凭证撤销请求SAP响应结果 message=========\n" + messageCancelAnomaly);
                JSONObject RETURN_DATA_Anomaly = messageCancelAnomaly.getJSONObject("RESPONSE").getJSONObject("RETURN_DATA");
                if (SAP_SUCCESS.equals(RETURN_DATA_Anomaly.getString("O_TYPE"))) {
                    String cancelVoucherNumber = RETURN_DATA_Anomaly.getString("0_MBLNR");
                    overseaWhsMove.setCancelPostingDate(cancelPostingDate);
                    overseaWhsMove.setCancelVoucherNumber(cancelVoucherNumber);
                    iOverseaOperateLogService.addOverseaOperateLog(userId, uuid, OVERSEA_WHS_MOVE_CANCEL_SAP.getDescZh() + ":" + cancelVoucherNumber,
                            OVERSEA_WHS_MOVE_CANCEL_SAP.getDescEn(), sapLog, dataToSapCancelAnomaly.toJSONString(), messageCancelAnomaly.toJSONString(), "");

                    ResponseResult updateInv = updateWhsStorageInventory(uuid, userId, true);
                    if (updateInv.getCode() != SUCCESS){
                        log.info("=======RuntimeException=========\n" + updateInv.getMsg());
                        throw new RuntimeException("储位库存更新错误\n" + updateInv.getMsg());
                    }
                    overseaWhsMove.setSpmsStatus(OVERSEA_WHS_MOVE_UPDATE.getCode());
                    this.baseMapper.update(overseaWhsMove, queryWrapper);
                    iOverseaOperateLogService.addOverseaOperateLog(userId, uuid, OVERSEA_WHS_MOVE_CANCEL.getDescZh(), OVERSEA_WHS_MOVE_CANCEL.getDescEn(), "");
                    return ResponseResult.success().add("overseaWhsMove", getOverseaWhsMoveByUuid(uuid))
                            .add("overseaWhsMoveDtl", getOverseaWhsMoveDtlList(uuid));
                } else {
                    overseaWhsMove.setCancelPostingDate(cancelPostingDate);
                    this.baseMapper.update(overseaWhsMove, queryWrapper);
                    iOverseaOperateLogService.addOverseaOperateLog(userId, uuid, OVERSEA_WHS_MOVE_CANCEL_ERROR.getDescZh(),
                            OVERSEA_WHS_MOVE_CANCEL_ERROR.getDescEn(), sapLog, dataToSapCancelAnomaly.toJSONString(), messageCancelAnomaly.toJSONString(), "");
                    return ResponseResult.error().add("overseaWhsMove", getOverseaWhsMoveByUuid(uuid))
                            .add("overseaWhsMoveDtl", getOverseaWhsMoveDtlList(uuid))
                            .add("sapReturnedMessage", messageCancelAnomaly)
                            .add("dataToSap", dataToSapCancelAnomaly);
                }
            } else {
                return ResponseResult.error("请求调拨任务当前状态错误");
            }
        } catch (FeignException feignException) {
            feignException.printStackTrace();
            return ResponseResult.error("请求SAP失败 FeignException").add("error", feignException.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ResponseResult.error("提交SAP失败 Exception").add("error", e.getMessage());
        }
    }

    ResponseResult checkCancel(String uuid, Integer dataVersion, String cancelPostingDate){
        if (StringUtils.isEmpty(uuid) || dataVersion == null){
            return ResponseResult.error("请求参数uuid或数据版本号不允许为空");
        }
        OverseaWhsMove overseaWhsMove = this.baseMapper.selectOne(new QueryWrapper<OverseaWhsMove>().eq("UUID", uuid));
        if (overseaWhsMove == null){
            return ResponseResult.error("请求调拨任务不存在");
        }
        if (!dataVersion.equals(overseaWhsMove.getDataVersion())){
            return ResponseResult.error("请求调拨任务已更新，请刷新重试");
        }
        String spmsStatus = overseaWhsMove.getSpmsStatus();
        if (!OVERSEA_WHS_MOVE_SUBMIT.getCode().equals(spmsStatus) &&
                !OVERSEA_WHS_MOVE_SUBMIT_SAP_ERROR.getCode().equals(spmsStatus) &&
                !OVERSEA_WHS_MOVE_SUBMIT_SAP.getCode().equals(spmsStatus)){
            return ResponseResult.error("请求调拨任务当前状态禁止此操作");
        }
        if (OVERSEA_WHS_MOVE_SUBMIT_SAP.getCode().equals(spmsStatus)){
            if (StringUtils.isEmpty(cancelPostingDate)){
                return ResponseResult.error("撤销过账日期不允许为空");
            }
        }
        List<OverseaWhsMoveDtl> overseaWhsMoveDtlList = iOverseaWhsMoveDtlService.list(new QueryWrapper<OverseaWhsMoveDtl>().eq("UUID", uuid));
        for (int k = 0; k < overseaWhsMoveDtlList.size(); k ++){
            OverseaWhsMoveDtl overseaWhsMoveDtl = overseaWhsMoveDtlList.get(k);
            String item = overseaWhsMoveDtl.getItemNo();
            String materialNo = overseaWhsMoveDtl.getMaterialNo();
            String storageInfo = overseaWhsMoveDtl.getActualStorageInfoMoveIn();
            double actualQtyBasicUnit = overseaWhsMoveDtl.getActualQtyMoveIn();
            if (actualQtyBasicUnit > 0){
                if (StringUtils.isEmpty(storageInfo)){
                    return ResponseResult.error("实际调入数量大于0的行:" + item + "，料号:" + materialNo + "储位信息无效");
                }
                //storageInfoArray 结构参考：[{"storageUuid":"cbd9576a4e53461fe0530101007f3e24","qty":5,"storageNo":"A010101","unitValue":5}]
                JSONArray storageInfoArray = JSONArray.parseArray(storageInfo);
                for (int i = 0; i < storageInfoArray.size(); i ++){
                    JSONObject storageInfoObj = storageInfoArray.getJSONObject(i);
                    String storageUuid = storageInfoObj.getString("storageUuid");
                    double qty = storageInfoObj.getDoubleValue("qty");
                    String storageNo = storageInfoObj.getString("storageNo");
                    if (qty > 0){
                        WhsStorageInventory whsStorageInventory = iWhsStorageInventoryService.getWhsStorageInventory(storageUuid, materialNo);
                        if (whsStorageInventory == null){
                            return ResponseResult.error("物料号" + materialNo + "在储位" + storageNo + "无可用库存");
                        }
                        if (qty > whsStorageInventory.getAvailableQty()){
                            return ResponseResult.error("物料号" + materialNo + "在储位" + storageNo + "可用库存不足");
                        }
                    }
                }
            }
        }
        return ResponseResult.success();
    }

}



